﻿using Microsoft.Xaml.Behaviors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace DailyApp.WPF.Extensions
{
    /// <summary>
    /// 密码框的扩展--解决了扩展属性发生变化，改变密码框密码
    /// 
    /// ***这块的逻辑非常重要！！！
    /// 
    /// 1.我们为PasswordBox添加了一个附加属性，但是没有改变原来的行为，这在第二个类中可以看到，我们基于了base
    /// 2.错误理解：误把登录窗体的密码框输入想象成在给附加属性进行输入！！！这是错误的！！！因为行为没有改变，我们还是在给密码进行输入
    /// 3.因此执行逻辑不是先改变附加属性，然后由附加属性的变化改变密码，这是错误的！！！
    /// 
    /// 正确逻辑：
    /// 我们在密码框输入密码 --> 由于基于base，因此密码改变 --> 密码改变引起附加属性改变 --> 附加属性改变进入 if (pwdBox != null && pwdBox.Password != newPwd)
    /// 这个判断 --> 自然而然附加属性一定和密码相同（因为密码改变就修改了附加属性） -->因此不会由附加属性修改密码，不重置密码，光标便不会从头开始。
    /// 
    /// 疑惑点：
    /// 那这么做岂不是密码永远和附加属性相同？其实这是错误理解，只有由输入密码这个行为触发的修改密码才会按照这个逻辑走，如果不触发行为，那么逻辑便是由先修改附加属性开始！！！
    /// </summary>
    public class PasswordBoxExtend
    {
        /// <summary>
        /// passwordBox的扩展属性
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>

        // Using a DependencyProperty as the backing store for Pwd.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PwdProperty =
            DependencyProperty.RegisterAttached("Pwd",
            typeof(string),
            typeof(PasswordBoxExtend),
            new PropertyMetadata("", OnPwdChanged));

        public static string GetPwd(DependencyObject obj)
        {
            return (string)obj.GetValue(PwdProperty);
        }

        public static void SetPwd(DependencyObject obj, string value)
        {
            obj.SetValue(PwdProperty, value);
        }

        /// <summary>
        /// 密码改变时候执行的方法
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnPwdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            //准备
            PasswordBox pwdBox = d as PasswordBox;//若d不能成功转换则返回null
            string newPwd = (string)e.NewValue;

            //类型及逻辑检查检查
            if (pwdBox != null && pwdBox.Password != newPwd)
            {
                pwdBox.Password = newPwd;//设置为新密码
            }
        }
    }

    /// <summary>
    /// 扩展(重写)行为--解决了密码框属性变化，改变扩展属性
    /// </summary>
    public class PasswordBoxBehavior : Behavior<PasswordBox>
    {
        /// <summary>
        /// 附加 注入事件(时机发生在xaml中调用i:Interaction.Behaviors时候)
        /// </summary>
        protected override void OnAttached()
        {
            //基础我们没有改变，也就意味着我们每次输入密码都会被记录下来，这个和附加属性不一样
            base.OnAttached();

            //当密码发生改变时执行事件
            AssociatedObject.PasswordChanged += OnPasswordChanged;

        }

        /// <summary>
        /// 销毁 移除事件 保证安全性
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();//基础功能
            AssociatedObject.PasswordChanged -= OnPasswordChanged;
        }

        //密码发生改变时执行的方法
        private void OnPasswordChanged(object sender, RoutedEventArgs e)
        {
            //准备
            PasswordBox passwordBox = sender as PasswordBox;
            string attachedPassword = PasswordBoxExtend.GetPwd(passwordBox);//此时附加属性还是旧的

            //修改附加属性的值
            if (passwordBox != null && passwordBox.Password != attachedPassword)
            {
                PasswordBoxExtend.SetPwd(passwordBox, passwordBox.Password);
            }
        }
    }
}
